﻿using System;
using System.Text;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Linq.Expressions;
using System.Web.Routing;

namespace RBAC.Web.CustomHelpers
{
    public static class HtmlExtensions
    {
        public static MvcHtmlString RadioButtonForSelectList<TModel, TProperty>(
            this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TProperty>> expression, SelectList RadioOptions)
        {
            var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            StringBuilder sb = new StringBuilder();
            if (RadioOptions != null)
            {
                // put a similar foreach here
                foreach (var myOption in RadioOptions)
                {
                    // Generate an id to be given to the radio button field 
                    var id = string.Format("{0}_{1}", metaData.PropertyName, myOption.Value);
                    sb.Append(htmlHelper.RadioButtonFor(expression, myOption.Value, new { id = id }) + myOption.Text);
                }
            }
            return new MvcHtmlString(sb.ToString());
        }

		public static MvcHtmlString DropDownListWithDefaultValueFor<TModel, TProperty>(
            this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TProperty>> expression, SelectList Options)
        {
            var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            StringBuilder sb = new StringBuilder();
             sb.Append(String.Format("<select id=\"{0}\" name=\"{0}\">", metaData.PropertyName));
             if (Options != null)
             {
                 // put a similar foreach here
                 foreach (var myOption in Options)
                 {
                     string selected = "";
                     if (metaData.Model.ToString().Equals(myOption.Value))
                     {
                         selected = "selected";
                     }
                     sb.Append(String.Format("<option value=\"{0}\" {1}>{2}</option>", myOption.Value, selected, myOption.Text));
                 }
             }
             sb.Append("</select>");
            return new MvcHtmlString(sb.ToString());
        }

        public static MvcHtmlString LookupFor<TModel, TProperty>(
            this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TProperty>> expression, String className, String itemCode, String itemName)
        {
            StringBuilder sb = new StringBuilder();
            var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);
             

            string ButtonName = className + "Btn";
            string SearchName = className + "Code";
            string FillDataName = className + "Name";
            sb.Append(String.Format("<input type=\"text\" id=\"{0}\" class=\"txtFillCode\" maxlength=\"10\" {1}/>", SearchName, itemCode != null && itemCode.Equals("") ? "" : "value=\"" + itemCode + "\""));
            sb.Append(String.Format("<input type=\"button\" id=\"{0}\" value=\"...\" class=\"btnLookup\" />", ButtonName));
            sb.Append(String.Format("<input type=\"text\" id=\"{0}\" class=\"txtFillName\" readonly=\"readonly\" {1}/>", FillDataName, itemName != null && itemName.Equals("") ? "" : "value=\"" + itemName + "\""));
            sb.Append(String.Format("<input type=\"hidden\" id=\"{0}GetLookup\" value=\"{1}\" />", className, urlHelper.Action(className+"GetLookup", "Popup")));
            sb.Append(String.Format("<input type=\"hidden\" id=\"{0}PopLookup\" value=\"{1}\" />", className, urlHelper.Action(className+"PopLookup", "Popup")));

            sb.Append(htmlHelper.HiddenFor(expression, new {id = className, @class = "TextLookup"}));

            return new MvcHtmlString(sb.ToString());
        }

        public static LookupHtmlBuilder<TModel> Lookup<TModel>(
           this HtmlHelper<TModel> htmlHelper, String className)
        {
            return new LookupHtmlBuilder<TModel>(htmlHelper, className);
        }

        public static ExternalLookupHtmlBuilder<TModel, TProperty> ExternalLookup<TModel, TProperty>(
           this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> property, String className)
        {
            return new ExternalLookupHtmlBuilder<TModel, TProperty>(htmlHelper, property, className);
        }



        public static MvcHtmlString DatePickerFor<TModel, TProperty>(
            this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TProperty>> expression, string id, bool ReadOnly)
        {
            var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            DateTime value = (DateTime)metadata.Model;

            StringBuilder sb = new StringBuilder();
            if (ReadOnly)
            {
                sb.Append(htmlHelper.TextBoxFor(expression, new { @disabled = "disabled", @Value = value.ToString("dd/MM/yyyy") }));
                sb.Append(htmlHelper.HiddenFor(expression, new { @Value = value.ToString("dd/MM/yyyy") }));
                //sb.Append(htmlHelper.EditorFor(expression, new { @disabled = "disabled" }));
            }
            else
            {
                sb.Append(htmlHelper.TextBoxFor(expression, new { @Value = value.ToString("dd/MM/yyyy") }));
                //sb.Append(htmlHelper.EditorFor(expression));
            }
            return new MvcHtmlString(sb.ToString());
        }



        //public static MvcHtmlString DatePickerFor<TModel, TProperty>(
        //    this HtmlHelper<TModel> htmlHelper,
        //    Expression<Func<TModel, TProperty>> expression, string id)
        //{
        //    StringBuilder sb = new StringBuilder();
        //    sb.Append(htmlHelper.EditorFor(expression, new { id = id }));
        //    return new MvcHtmlString(sb.ToString());
        //}

        public static MvcHtmlString DisplayMessage<TModel>(this HtmlHelper<TModel> htmlHelper, string message, bool? isSuccess)
        {
            if (isSuccess != null)
            {
                StringBuilder sb = new StringBuilder();
                string htmlClass = "";
                if (isSuccess.Value)
                    htmlClass = "operation-success";
                else
                    htmlClass = "operation-failure";
                sb.Append(String.Format("<div class=\"{0}\"><span>{1}</span></div>", htmlClass, message));
                return new MvcHtmlString(sb.ToString());
            }
            else
            {
                return new MvcHtmlString("");
            }
        }

        public static MvcHtmlString Pager(this HtmlHelper helper, int pageNumber, int pageSize, int totalRec, String code, String name, String sort, String sortdir, object routeValues)
        {
            // how many pages to display in each page group const   
            int cGroupSize = 5;
            int middlePage = (int)Math.Ceiling(cGroupSize / (double)2);

            var TotalPages = (int)(totalRec / pageSize);
            if (totalRec % pageSize > 0)
                TotalPages++;

            var urlHelper = new UrlHelper(helper.ViewContext.RequestContext, helper.RouteCollection);
            var container = new TagBuilder("div");
            container.AddCssClass("pager");
            var actionName = helper.ViewContext.RouteData.GetRequiredString("Action");

            if (pageNumber > 1)
            {
                var first = new TagBuilder("a");
                first.SetInnerText("first ");
                first.AddCssClass("page-numbers prev");
                var routingValues = new RouteValueDictionary(routeValues);
                routingValues.Add("page", 1);
                routingValues.Add("pageSize", pageSize);
                routingValues.Add("sort", sort);
                routingValues.Add("sortdir", sortdir);
                routingValues.Add("code", code);
                routingValues.Add("name", name);
                first.MergeAttribute("href", urlHelper.Action(actionName, routingValues));
                container.InnerHtml += first.ToString();
            }

            if (pageNumber != 1)
            {
                var prev = new TagBuilder("a");
                prev.SetInnerText("prev");
                prev.AddCssClass("page-numbers prev");
                var routingValues = new RouteValueDictionary(routeValues);
                routingValues.Add("page", pageNumber - 1);
                routingValues.Add("pageSize", pageSize);
                routingValues.Add("sort", sort);
                routingValues.Add("sortdir", sortdir);
                routingValues.Add("code", code);
                routingValues.Add("name", name);
                prev.MergeAttribute("href", urlHelper.Action(actionName, routingValues));
                container.InnerHtml += prev.ToString();
            }

            int start;
            if (pageNumber <= middlePage) start = 1;
            else if (pageNumber >= TotalPages - (middlePage - 2))
                start = TotalPages - (cGroupSize - 1);
            else
                start = pageNumber - (middlePage - 1);

            if (TotalPages > cGroupSize)
            {
                if (pageNumber > middlePage)
                {
                    var dot = new TagBuilder("a");
                    dot.SetInnerText(" ...");
                    dot.AddCssClass("page-numbers prev");
                    var routingValues = new RouteValueDictionary(routeValues);
                    routingValues.Add("page", (start - 1));
                    routingValues.Add("pageSize", pageSize);
                    routingValues.Add("sort", sort);
                    routingValues.Add("sortdir", sortdir);
                    routingValues.Add("code", code);
                    routingValues.Add("name", name);
                    dot.MergeAttribute("href", urlHelper.Action(actionName, routingValues));
                    container.InnerHtml += dot.ToString();
                }
            }
            for (int i = start; i < start + cGroupSize; i++)
            {
                if (i > TotalPages) continue;

                var page = new TagBuilder("a");
                page.SetInnerText(" " + i.ToString());
                var routingValues = new RouteValueDictionary(routeValues);
                routingValues.Add("page", i);
                routingValues.Add("pageSize", pageSize);
                routingValues.Add("sort", sort);
                routingValues.Add("sortdir", sortdir);
                routingValues.Add("code", code);
                routingValues.Add("name", name);

                if (i == pageNumber) //current page
                {
                    page.AddCssClass("page-numbers current");
                }
                else
                {
                    page.AddCssClass("page-numbers");
                }

                page.MergeAttribute("href", urlHelper.Action(actionName, routingValues));
                container.InnerHtml += page.ToString();
            }

            if (TotalPages > cGroupSize)
            {
                if (pageNumber + middlePage <= TotalPages)
                {
                    var dot = new TagBuilder("a");
                    dot.SetInnerText(" ...");
                    dot.AddCssClass("page-numbers next");
                    var routingValues = new RouteValueDictionary(routeValues);
                    if (pageNumber < middlePage)
                        routingValues.Add("page", (middlePage * 2));
                    else
                        routingValues.Add("pageNumber", (pageNumber + middlePage));

                    routingValues.Add("pageSize", pageSize);
                    routingValues.Add("sort", sort);
                    routingValues.Add("sortdir", sortdir);
                    routingValues.Add("code", code);
                    routingValues.Add("name", name);
                    dot.MergeAttribute("href", urlHelper.Action(actionName, routingValues));
                    container.InnerHtml += dot.ToString();
                }
            }

            if (pageNumber != TotalPages)
            {
                var next = new TagBuilder("a");
                next.SetInnerText(" next");
                next.AddCssClass("page-numbers next");
                var routingValues = new RouteValueDictionary(routeValues);
                routingValues.Add("page", pageNumber + 1);
                routingValues.Add("pageSize", pageSize);
                routingValues.Add("sort", sort);
                routingValues.Add("sortdir", sortdir);
                routingValues.Add("code", code);
                routingValues.Add("name", name);
                next.MergeAttribute("href", urlHelper.Action(actionName, routingValues));
                container.InnerHtml += next.ToString();
            }

            if (pageNumber < TotalPages)
            {
                var last = new TagBuilder("a");
                last.SetInnerText(" last");
                last.AddCssClass("page-numbers next");
                var routingValues = new RouteValueDictionary(routeValues);
                routingValues.Add("page", TotalPages);
                routingValues.Add("pageSize", pageSize);
                routingValues.Add("sort", sort);
                routingValues.Add("sortdir", sortdir);
                routingValues.Add("code", code);
                routingValues.Add("name", name);
                last.MergeAttribute("href", urlHelper.Action(actionName, routingValues));
                container.InnerHtml += last.ToString();
            }

            return MvcHtmlString.Create(container.ToString());
        }

        public static MvcHtmlString PartialFor<TModel, TProperty>(this HtmlHelper<TModel> helper, System.Linq.Expressions.Expression<Func<TModel, TProperty>> expression, string partialViewName)
        {
            string name = ExpressionHelper.GetExpressionText(expression);
            object model = ModelMetadata.FromLambdaExpression(expression, helper.ViewData).Model;
            var viewData = new ViewDataDictionary(helper.ViewData)
            {
                TemplateInfo = new System.Web.Mvc.TemplateInfo
                {
                    HtmlFieldPrefix = name
                }
            };

            return helper.Partial(partialViewName, model, viewData);

        }

    }
}